﻿using ChoMy.Models;
using ChoMy.Models.Data;
using ChoMy.Payment;
using FAMailUtils.MailGun;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace ChoMy.Controllers
{
    [Authorize]
    public class PaymentController : Controller
    {
        private ChoMyContext db = new ChoMyContext();
        private ApplicationDbContext ac = new ApplicationDbContext();
        private OnePayHandling oh = new OnePayHandling();

        public ActionResult Index(int? receiverId)
        {
            // Không có mã người nhận
            if (receiverId == null)
            {
                return RedirectToAction("BadRequest", "Error");
            }

            Receiver receiver = db.Receivers.Find(receiverId);

            // Không tìm thấy người nhận hoặc người nhận không thuộc người dùng
            if (receiver == null || receiver.CreatedBy != User.Identity.Name)
            {
                return RedirectToAction("NotFound", "Error");
            }

            // Giỏ hàng rỗng
            if (!db.ShoppingCarts.Where(x => x.CreatedBy == User.Identity.Name).Any())
            {
                return RedirectToAction("Index", "Home");
            }

            ViewBag.ReceiverId = receiver.Id;

            // Mã đơn hàng
            Session["OrderCode"] = Path.GetRandomFileName().Replace(".", "").ToUpper();

            return View();
        }

        [HttpPost]
        public ActionResult Checkout(Checkout checkout, int receiverId, string againLink)
        {
            OnePayRedirect opr = new OnePayRedirect();

            float exchangeRate = GetExchangeRate(); // Tỷ giá VND/USD

            float amount = db.ShoppingCarts
                .Where(x => x.CreatedBy == User.Identity.Name)
                .Sum(x => x.Style.UnitPrice * x.Quantity);

            float vat = amount * 10 / 100; // Thuế VAT

            amount = (amount + vat) * exchangeRate; // Tổng tiền (chưa làm tròn)

            opr.Amount = (Math.Round(amount / 1000) * 1000 * 100).ToString(); // Tổng tiền (VND)

            opr.OrderInfo = Session["OrderCode"] as String; // Mã đơn hàng

            opr.TicketNo = Request.UserHostAddress; // IP

            opr.MerchTxnRef = Path.GetRandomFileName(); 

            opr.AgainLink = againLink; 

            if (checkout.PaymentType == "Inland")
            {
                opr.Title = "Thanh toán trực tuyến bằng thẻ ATM 23 ngân hàng";

                string returnUrl = Url.Action("Confirmation", null, new
                {
                    paymentType = "inland",
                    receiverId = receiverId
                }, Request.Url.Scheme);

                return Redirect(oh.Redirect(opr, true, returnUrl));
            }
            else
            {
                opr.Title = "Thanh toán trực tuyến bằng thẻ VISA, MASTER, JCB";

                string returnUrl = Url.Action("Confirmation", null, new
                {
                    paymentType = "international",
                    receiverId = receiverId
                }, Request.Url.Scheme);

                return Redirect(oh.Redirect(opr, false, returnUrl));
            }
        }

        public ActionResult Confirmation(string paymentType, int receiverId)
        {
            OnePayResponse opr = new OnePayResponse();

            if (paymentType == "inland")
            {
                opr = oh.Response(true, Request.QueryString);
            }
            else
            {
                opr = oh.Response(false, Request.QueryString);
            }

            if (opr.HashValidateResult != "INVALIDATED")
            {
                Order order = db.Orders.FirstOrDefault(x => x.Code == opr.OrderInfo);

                if(order == null)
                {
                    Receiver receiver = db.Receivers.Find(receiverId);

                    // Tạo mới đơn hàng
                    order = new Order();
                    order.Code = opr.OrderInfo;
                    order.Name = receiver.Name;
                    order.Address = receiver.Address;
                    order.Phone = receiver.Phone;
                    order.Email = receiver.Email;

                    order.PaymentStatus = opr.TxnResponseCode.Trim(); // Tình trạng thanh toán

                    db.Orders.Add(order);
                    db.SaveChanges();

                    // Tạo mới chi tiết đơn hàng
                    List<ShoppingCart> spCarts = db.ShoppingCarts
                        .Where(x => x.CreatedBy == User.Identity.Name)
                        .ToList();

                    foreach (ShoppingCart sc in spCarts)
                    {
                        var os = new OrderStyle();
                        os.OrderId = order.Id;
                        os.StyleId = sc.StyleId;
                        os.Quantity = sc.Quantity;

                        db.OrderStyles.Add(os);
                    }

                    db.SaveChanges();

                    // Thành toán thành công
                    if(order.PaymentStatus == "0")
                    {
                        // Xóa giỏ hàng
                        db.ShoppingCarts.RemoveRange(spCarts);
                        db.SaveChanges();

                        // Gửi mail xác nhận đơn hàng
                        string mailContent = PartialViewToString("__MailOrder", order.Id);
                        SendMailOrder(mailContent, User.Identity.Name, order.Code);
                    }  
                }

                ViewBag.OrderId = order.Id;
                ViewBag.ReceiverId = receiverId;
                ViewBag.CheckoutDate = order.DateCreated;
            }

            return View(opr);
        }

        // Mẫu mail xác nhận đơn hàng
        public ActionResult _MailOrder(int orderId)
        {
            Order order = db.Orders.Find(orderId);

            ViewBag.Sender = ac.Users.First(x => x.UserName == User.Identity.Name);
            ViewBag.ExchangeRate = GetExchangeRate();

            return PartialView(order);
        }

        // PV người nhận
        public ActionResult _Sender()
        {
            ApplicationUser user = ac.Users
                .FirstOrDefault(x => x.UserName == User.Identity.Name);

            return PartialView(user);
        }

        // PV người gửi
        public ActionResult _Receiver(int id)
        {
            Receiver receiver = db.Receivers.Find(id);

            return PartialView(receiver);
        }

        // PV chi tiết sản phẩm trong giỏ hàng
        public ActionResult _ShoppingCarts()
        {
            List<ShoppingCart> shoppingCarts = db.ShoppingCarts
                .Where(x => x.CreatedBy == User.Identity.Name)
                .OrderBy(x => x.Style.Product.Name)
                .ToList();

            ViewBag.ExchangeRate = GetExchangeRate();

            return PartialView(shoppingCarts);
        }

        // PV chi tiết sản phẩm trong hóa đơn
        public ActionResult _OrderStyles(int orderId)
        {
            List<OrderStyle> orderStyles = db.OrderStyles
                .Where(x => x.OrderId == orderId)
                .ToList();

            ViewBag.ExchangeRate = GetExchangeRate();

            return PartialView(orderStyles);
        }

        // PV thanh toán OnePay
        public ActionResult _OnePay()
        {
            // Chính sách đổi/trả hàng
            Post post = db.Posts.FirstOrDefault(x => x.NameId == "doi-tra-hoan-tien");

            ViewBag.PaymentRules = (post == null ? "" : post.Description);

            // Chính sách vận chuyển
            post = db.Posts.FirstOrDefault(x => x.NameId == "mien-phi-van-chuyen");

            ViewBag.ShippingRules = (post == null ? "" : post.Description);

            return PartialView(new Checkout());
        }

        #region Helpers
        // Hàm gửi mail
        private void SendMailOrder(string content, string email, string orderCode)
        {
            string domain = "chomy.com.vn";
            string subject = "Xác nhận đơn hàng " + orderCode;
            string body = content;
            string senderName = "Chợ Mỹ";
            string sender = "noreply@chomy.com.vn";
            List<string> emails = new List<string> { email };

            SendMail sendMail = new SendMail("key-0hvxsu9bubvdc9060do5rn44z3masyw0");
            sendMail.SendHtmlMessage(domain, senderName, sender, emails, subject, body);
        }

        // Chuyển PV -> String
        private string PartialViewToString(string viewName, object model)
        {
            ViewData.Model = model;
            using (var sw = new StringWriter())
            {
                var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
                var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
                viewResult.View.Render(viewContext, sw);
                viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
                return sw.GetStringBuilder().ToString();
            }
        }

        // Chuyển USD -> VND
        private float GetExchangeRate()
        {
            return float.Parse(db.Settings.First(x => x.Name == "ExchangeRate").Value);
        }

        // Đóng kết nối CSDL
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                db.Dispose();
            }

            base.Dispose(disposing);
        }
        #endregion
    }
}